package edu.xmut.yuepaibackend.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import edu.xmut.yuepaibackend.model.domain.User;
import edu.xmut.yuepaibackend.model.domain.UserAbout;
import edu.xmut.yuepaibackend.model.domain.UserInfo;
import edu.xmut.yuepaibackend.model.dto.RedisUserDTO;
import edu.xmut.yuepaibackend.model.form.UserLoginForm;
import edu.xmut.yuepaibackend.model.vo.UserInfoVO;
import edu.xmut.yuepaibackend.service.UserAboutService;
import edu.xmut.yuepaibackend.service.UserInfoService;
import edu.xmut.yuepaibackend.service.UserService;
import edu.xmut.yuepaibackend.mapper.UserMapper;
import edu.xmut.yuepaibackend.utils.*;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

import static edu.xmut.yuepaibackend.constant.RedisConstants.USER_INFO_KEY;
import static edu.xmut.yuepaibackend.constant.RedisConstants.USER_LOGIN_CODE_KEY;

/**
 * @author tanjiao
 * @description 针对表【user(用户表)】的数据库操作Service实现
 * @createDate 2024-08-28 22:08:51
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService {

    @Resource
    private RedisCacheUtils redisCacheUtils;

    @Resource
    private UserInfoService userInfoService;

    @Resource
    private UserAboutService userAboutService;

    @Resource
    private IpUtils ipUtils;

    @Override
    public String loginByCode(String phone, String code) {
        // 根据手机号查询用户
        User user = lambdaQuery().eq(User::getTelephone, phone).one();
        if (Objects.isNull(user)) {
            throw new BizException("用户不存在");
        }
        // 从redis取出验证码
        String cacheCode = redisCacheUtils.get(USER_LOGIN_CODE_KEY + phone);
        if (StrUtil.isBlank(cacheCode)) {
            throw new BizException("验证码不存在或已过期");
        }
        // 校验验证码是否一致
        if (!Objects.equals(cacheCode, code)) {
            throw new BizException("验证码错误");
        }
        // 生成JWT
        String token = JwtUtil.createJWT(user.getId().toString());
        // 往redis存用户信息，用于检测是否登录
        UserInfo userInfo = userInfoService.getById(user.getId());
        RedisUserDTO redisUserDTO = new RedisUserDTO(user, userInfo);
        redisUserDTO.setCurrentToken(token);
        redisCacheUtils.set(USER_INFO_KEY + user.getId(), redisUserDTO, 6, TimeUnit.HOURS);
        return token;
    }

    @Override
    public String getCode(String phone) {
        // 判断验证码是否已经生成
        String cacheCode = redisCacheUtils.get(USER_LOGIN_CODE_KEY + phone);
        if (StrUtil.isNotBlank(cacheCode)) {
            throw new BizException("验证码已生成，请1分钟之后在尝试");
        }
        // 先校验手机号是否存在
        long count = lambdaQuery().eq(User::getTelephone, phone).count();
        if (count == 0) {
            throw new BizException("用户不存在");
        }
        // 得到生成的数字验证码
        String code = RandomUtil.randomNumbers(6);
        // 往redis里面存验证码
        redisCacheUtils.set(USER_LOGIN_CODE_KEY + phone, code, 1, TimeUnit.MINUTES);
        return code;
    }

    @Override
    public String loginByPassword(UserLoginForm userLoginForm) {
        String phone = userLoginForm.getPhone();
        String password = userLoginForm.getPassword();
        // 从数据库中查询用户
        User user = lambdaQuery().eq(User::getTelephone, phone).one();
        if (Objects.isNull(user)) {
            throw new BizException("用户不存在");
        }
        // 判断密码是否一致
        if (!Objects.equals(password, user.getPassword())) {
            throw new BizException("密码错误");
        }
        // 生成JWT
        String token = JwtUtil.createJWT(user.getId().toString());
        UserInfo userInfo = userInfoService.getById(user.getId());
        // 往redis存用户信息，用于检测是否登录
        RedisUserDTO redisUserDTO = new RedisUserDTO(user, userInfo);
        redisUserDTO.setCurrentToken(token);
        redisCacheUtils.set(USER_INFO_KEY + user.getId(), redisUserDTO, 6, TimeUnit.HOURS);
        return token;
    }

    @Override
    public UserInfoVO getMyInfo() {
        // 从本地线程拿到用户id
        Long userId = UserContext.getUserId();
        // 根据用户id拿到用户的所有信息
        User user = this.getById(userId);
        UserInfo userInfo = userInfoService.getById(userId);
        UserAbout userAbout = userAboutService.getById(userId);
        // 创建vo，合并属性
        UserInfoVO userInfoVO = new UserInfoVO();
        BeanUtil.copyProperties(user, userInfoVO);
        BeanUtil.copyProperties(userInfo, userInfoVO);
        BeanUtil.copyProperties(userAbout, userInfoVO);
        // 查询IP归属地
        String ipRegion = ipUtils.getIpRegion(user.getIp());
        if (StrUtil.isNotBlank(ipRegion)) {
            userInfoVO.setIP(ipRegion);
        }else {
            userInfoVO.setIP("未知");
        }
        return userInfoVO;
    }
}




